package com.kitty.game.fight.bean;

import com.kitty.game.ServerService;   //3
import com.kitty.game.role.model.Role;
import com.kitty.game.config.Xing;  //
import com.kitty.common.utils.SpringUtils;    //1
import com.kitty.common.core.SchedulerManager;    //2
import com.kitty.game.activity.service.other.SuperBossHandler;  //4
import com.kitty.game.fight.message.RespCombatWaitAllEnd;  //5
import com.kitty.game.fight.service.FightExecutorService;
import com.kitty.game.fight.service.FightMessageService;
import com.kitty.game.fight.service.FightService;
import com.kitty.game.fight.task.TimeOutTask;
import com.kitty.game.fight.util.FightMessageUtil;
import com.kitty.game.fight.util.FightRateUtil;
import com.kitty.game.utils.Const;
import com.kitty.game.waiguan.CustomFasionIcon;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.nutz.lang.util.NutMap;

import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicInteger;
//后写
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 战场对象
 */
@Data
@Slf4j
public class Fight {



    private final static AtomicInteger idFactory = new AtomicInteger(1);

    private int id;
    private int leaderId;
    private long createTime;
    private List<FightObject> listA = new ArrayList<>();
    private List<FightObject> listB = new ArrayList<>();
    protected int mapId;
    private int type;// 1 野怪战斗 2 PK战斗 3 除暴 4 刷道 5 BOSS 7挑战星君
    private int round = 1;// 回合数
    private int maxRound = 150; //最大回合数
    private int taskId;// 任务id
    private NutMap expMap;// 只在野怪战斗时使用
    private NutMap bossReward;
    protected int npcId;
    private NutMap data;
    private ScheduledFuture<?> nextRoundTimer;
    /**
     * 初始化战场的时候初始化一下自定义时装
     */
    private List<CustomFasionIcon> customIconListA = createCustomFasionIcons();
    private List<CustomFasionIcon> customIconListB = createCustomFasionIcons();

    private ScheduledFuture<?> timeOutTask;

    /**
     * 本回合是否开始计算 key :回合数 value:true or false
     */
    private Set<Integer> isCompleted = new HashSet<>();


    private Map<Integer, FightObject> fightActors = new HashMap<>();

    /**
     * 已经死过一次的宠物列表
     */
    private Set<Integer> deadPetIds = new HashSet<>();

    /**
     * 判断当前回合是否操作过
     * 如果返回真说明操作过了,不做处理
     * 没有出手才继续之后的代码
     */
    private boolean isCompleted(int round) {
        boolean boo = isCompleted.contains(round);
        if (!boo) {
            isCompleted.add(round);
        }
        return boo;
    }

    /**
     * 不同回合法宝失效的目标(卸甲金葫专用)
     */
    private Map<Integer, Set<Integer>> roundInvalidFabao = new HashMap<>();

    /**
     * 主人的定时任务
     */
    private Map<Integer, ScheduledFuture<?>> fightId_timer_host = new HashMap<>();
    /**
     * 宠物的定时任务
     */
    private Map<Integer, ScheduledFuture<?>> fightId_timer_pet = new HashMap<>();

    protected FightService fightService = SpringUtils.getFightService();

    public List<CustomFasionIcon> createCustomFasionIcons() {
        List<CustomFasionIcon> customIconList = new ArrayList<>(10);
        for (int i = 0; i < 10; i++) {
            CustomFasionIcon customFasionIcon = new CustomFasionIcon();
            customIconList.add(customFasionIcon);
        }
        return customIconList;
    }

    public Fight(int type) {
        this.id = idFactory.getAndIncrement();
        this.createTime = System.currentTimeMillis();
        this.type = type;
    }

    public ArrayList<FightObject> getAllFightObjects() {
        ArrayList<FightObject> container = new ArrayList<>();
        for (FightObject object : listA) {
            if (object != null) {
                container.add(object);
            }
        }
        for (FightObject object : listB) {
            if (object != null) {
                container.add(object);
            }
        }
        return container;
    }


    public FightObject queryFightObject(int roleId) {
        if (getListA() != null) {
            for (FightObject fightObject : getListA()) {
                if (fightObject.getId() == roleId) {
                    return fightObject;
                }
            }
        }
        if (getListB() != null) {
            for (FightObject fightObject : getListB()) {
                if (fightObject.getId() == roleId) {
                    return fightObject;
                }
            }
        }
        return null;
    }

    public FightObject getAttackTarget(FightObject effector) {
        List<FightObject> targets = effector.isASide ? getListB() : getListA();
        for (FightObject target : targets) {
            if (!target.isFallDown()) {
                return target;
            }
        }
        return null;
    }

    public FightObject getAttackSelf(FightObject effector) {
        List<FightObject> targets = effector.isASide ? getListA() : getListB();
        for (FightObject target : targets) {
            if (!target.isFallDown()) {
                return target;
            }
        }
        return null;
    }

    public boolean isSameSide(FightObject o1, FightObject o2) {
        return o1.isASide == o2.isASide;
    }

    public List<FightObject> getMySide(int roleId) {
        for (FightObject fightObject : getListA()) {
            if (fightObject.getId() == roleId) {
                return getListA();
            }
        }
        return getListB();
    }

    public List<FightObject> getTargetSide(int roleId) {
        for (FightObject fightObject : getListA()) {
            if (fightObject.getId() == roleId) {
                return getListB();
            }
        }
        return getListA();
    }

    public boolean isWinner(int roleId) {
        List<FightObject> mySide = getMySide(roleId);
        for (FightObject fightObject : mySide) {
            if (fightObject.getCurrLife() > 0) {
                return true;
            }
        }
        return false;
    }

    /**
     * 战斗是否开始
     */
    public boolean isStartFight() {
        for (FightObject fightObject : getListA()) {
            if (!fightObject.isDoAction()) {
                return false;
            }
        }
        for (FightObject fightObject : getListB()) {
            if (!fightObject.isDoAction()) {
                return false;
            }
        }
//        boolean boo = !isCompleted(round);
        return true;//
    }

    public boolean isOver() {
        return isSideOver(getListA()) || isSideOver(getListB())
                || (getData() != null && getData().getBoolean("fight_result_fail", false))
                || (getData() != null && getData().getBoolean("fight_result_success", false));
    }

    public boolean isSideOver(List<FightObject> members) {
        if (members != null && members.size() > 0) {
            for (FightObject fightObject : members) {
                if (fightObject !=null && !fightObject.isFallDown()) {
                    return false;
                }
            }
        }
        return true;
    }


    /**添加宠物战场对象到列表中 需要根据主人的阵营添加*/
    public void addFightObject(FightObject addObject){
        fightActors.put(addObject.getId(), addObject);
        for (FightObject object : getListA()) {
            if (object.getId() == addObject.getHostId()) {
                getListA().add(addObject);
                return;
            }
        }
        for (FightObject fightObject : getListB()) {
            if (fightObject.getId() == addObject.getHostId()) {
                getListB().add(addObject);
                return;
            }
        }
    }
    /**
     * 删除战场目标
     *
     * @param fightObject
     */
    public void removeFightObject(FightObject fightObject) {
        /**宠物飞升时，宠物死亡则战斗失败*/
        if (getType() == Const.fightType_petFly && fightObject.isPet() && fightObject.getPos() == 8) {
            if (getData() == null) { setData(NutMap.NEW()); }
            getData().setv("fight_result_fail", true);
        }

        removeFightObject(getListA(), fightObject);
        removeFightObject(getListB(), fightObject);
    }

    private void removeFightObject(List<FightObject> pool, FightObject toRemove) {
        pool.removeIf(next -> next.getId() == toRemove.getId());
    }

    public void onActorDie(FightObject actor) {
        FightMessageService fightMessageService = SpringUtils.getFightMessageService();

        if (actor.isMonster() && !(actor.getBossSet() instanceof Xing)) {
            FightMessageUtil.sendFightPackage(this, fightMessageService.disappear(actor.getId()));
            removeFightObject(actor);
            SpringUtils.getBean(SuperBossHandler.class).checkFight(this);
        } else if (actor.isPet() || actor.isPetMirror()) {
            onPetDie(actor);
        }
    }

    private void onPetDie(FightObject actor) {
        boolean revive = FightRateUtil.petCanRevive(actor);
        FightMessageService fightMessageService = SpringUtils.getFightMessageService();
        if (revive) {
            FightMessageUtil.sendFightPackage(this, fightMessageService.revive(actor.getId()));
            FightMessageUtil.sendFightPackage(this, fightMessageService.petRelieveShouting(actor.getPet()));
            int currLife = actor.isPetMirror() ? actor.getMaxLife() : SpringUtils.getHurtService().countPetMaxLife(actor.getPet());
            actor.setCurrLife(currLife);
            FightMessageUtil.sendFightPackage(this, fightMessageService.updateTargetLife(actor.getId(), actor.getCurrLife()));
        } else {
            deadPetIds.add(actor.getId());

            FightMessageUtil.sendFightPackage(this, fightMessageService.disappear(actor.getId()));
            FightMessageUtil.sendFightPackage(this, new RespCombatWaitAllEnd());

            removeFightObject(actor);

            // 如果宠物死了还有掠阵宠物 并且掠阵的宠物不是当前宠物的话,把掠阵宠物加入战场
            FightObject host = queryFightObject(actor.getHostId());
            if (host != null && host.isPlayer()) {
                SpringUtils.getFightService().supplyPet(this, actor, host);
            }
        }
    }

    public boolean petDeadOnce(int petId) {
        return deadPetIds.contains(petId);
    }

    /**
     * 使目标当前回合的法宝失效
     * @param targetId
     */
    public void makeTargetArtifactInvalid(int targetId) {
        Set<Integer> targets = roundInvalidFabao.computeIfAbsent(round, k -> new HashSet<>());
//        logger.error("法宝失效=={}=={}",targetId,round);
        targets.add(targetId);
    }

    /**
     * 当前回合我的法宝失效
     * @param roleId
     * @return
     */
    public boolean isMyArtifactInvalid(int roleId) {
        Set<Integer> targets = roundInvalidFabao.get(round);
//        logger.error("法宝失效11111111=={}=={}={}",roleId,round,targets);
        if (targets == null) {
            return false;
        }
        return targets.contains(roleId);
    }

    /**
     * 查询战场元素，不管死活
     * @param objId
     * @return
     */
    public FightObject queryFightObjectAnyWay(int objId) {
        return fightActors.get(objId);
    }

  public void destroy() {
//        logger.info("fight[{}], type[{}]清除战场, 创建时间{}", getId(), getType(), TimeUtil.formatDate(new Date(), TimeUtil.DEFAULT_DATE_FORMAT));
        for (FightObject fightObject : getAllFightObjects()) {
            Integer temp = FightExecutorService.FIGHT_ROOMS.get(fightObject.getId());
            if (temp == null) {
                continue;
            }
            if (fightObject.isPlayer()) {
                Role role = fightObject.getRole();
                /**设置战斗结束时间*/
                if (role != null) {role.setPrevFightEndTime(System.currentTimeMillis());}
            }
            if (getId() == temp) {
                FightExecutorService.FIGHT_ROOMS.remove(fightObject.getId());
                FightExecutorService.PETID_ROLEID.remove(fightObject.getFightPetId());
            }
        }
        FightExecutorService.FIGHTS.remove(getId());

        cancelTask(timeOutTask);
        cancelTask(nextRoundTimer);
    }


    public void addHostTask(int roleId, ScheduledFuture<?> task) {
        removeHostTask(roleId);
        this.fightId_timer_host.put(roleId, task);
    }

    public void removeHostTask(int roleId) {
        ScheduledFuture<?> task = fightId_timer_host.get(roleId);
        if (task != null) {
            cancelTask(task);
            fightId_timer_host.remove(roleId);
        }
    }

    public void addPetTask(int roleId, ScheduledFuture<?> task) {
        removePetTask(roleId);
        this.fightId_timer_pet.put(roleId, task);
    }

    public void removePetTask(int memberId) {
        ScheduledFuture<?> task = fightId_timer_pet.get(memberId);
        if (task != null) {
            cancelTask(task);
            fightId_timer_host.remove(memberId);
        }
    }

    public void cancelTask(ScheduledFuture<?> task) {
        if (task != null && !task.isDone()) {
            task.cancel(Boolean.FALSE);
        }
    }

    public void start() {
        FightExecutorService fightExecutorService = SpringUtils.getBean(FightExecutorService.class);

        fightExecutorService.addFightTask(this, () -> {
            try {
                loadActors();
                notifyAndStart();
                for (FightObject object : getListA()) {
                    fightActors.put(object.getId(), object);
                }
                for (FightObject object : getListB()) {
                    fightActors.put(object.getId(), object);
                }
            } catch (Exception e){
                log.info("进入战斗出错:{}",e);
            }
        });
        SpringUtils.getBean(FightService.class).besure(this);
        // 设置结束超时任务
        TimeOutTask timeOut = new TimeOutTask(getId());
        ScheduledFuture<?> timeOutTask = SchedulerManager.getInstance().schedule(timeOut, 24000);
        setTimeOutTask(timeOutTask);
    }

    /**
     * 加载战场所有战斗单元
     */
    protected void loadActors() {

    }

    protected void notifyAndStart() {

    }

    /**
     * 判断是不是跟玩家战斗
     */
    public boolean isPkFight() {
        return false;
    }

    /**
     * 获得战斗对象中最大的id
     */
    public int getMaxFightObjectId() {
        int maxId = 0;
        ArrayList<FightObject> allFightObjects = getAllFightObjects();
        for (FightObject fightObject : allFightObjects) {
            if (fightObject.getId() > maxId) {
                maxId = fightObject.getId();
            }
        }
        return maxId;
    }

    /**是否使用月道行或者月武学*/
    public boolean isUseMonth() {
        if (SpringUtils.getBean(ServerService.class).getServer().getId() == 10000){
            return true;
        }
        return false;
//        return type == Const.fightType_month_shidao_yuanmo || type == Const.fightType_month_shidao_pk;
    }
}
